<template>
    <div class="editor-render">

        <!-- 背景 -->
        <div class="editor-render-mask"><canvas ref="mask"></canvas></div>

        <!-- 网格 -->
        <div class="editor-gridline-line" :style="renderStyle">
            <span v-for="(item, index) in gridlineStyle" :key="index" :style="item"></span>
        </div>

        <!-- 图层 -->
        <div class="editor-render-mapping" ref="mapping"></div>

        <!-- 边框 -->
        <div class="editor-gridline-border" :style="renderStyle"></div>
    </div>
</template>

<script>
import { fabric as Fabric } from "fabric";
import DesignEditor from "@/utils/DesignEditor.js";
import DesignResource from "@/utils/DesignResource.js";

export default {
    props: {
        zoom: { type: Boolean, default: false }, // 缩放
        gridline: { type: Boolean, default: false }, // 网格
        pieces: { type: Array, default: () => [] }, // 网格
        activeSurface: { type: Object, default: null }, // 网格
        activePiece: { type: Object, default: null }, // 网格
    },
    data () {
        return {
            scale: 1,
            renders: {},
        };
    },
    computed: {
        // 渲染器
        renderStyle () {
            if (!this.activePiece || !this.activeSurface) {
                return { display: 'none' }
            } else {
                const piece = this.activePiece;
                const surface = this.activeSurface;
                const mapperIndex = surface.mapping.findIndex(mapper => mapper.canvas_name == piece.canvas_name);
                const mapperActive = surface.mapping[mapperIndex];

                return {
                    width: 100 * mapperActive.width / surface.outer_width + '%',
                    height: 100 * mapperActive.height / surface.outer_height + '%',
                    left: 100 * mapperActive.x / surface.outer_width + '%',
                    top: 100 * mapperActive.y / surface.outer_height + '%',
                    transform: `rotate(${mapperActive.rotate}deg)`,
                }
            }
        },

        // 网格样式
        gridlineStyle () {
            if (!this.activePiece) {
                // 没有选中
                return [];
            } else if (!this.gridline) {
                // 不打开网格
                return [];
            } else {

                let list = [];
                let size = 100;
                let scale = 1;
                let width = this.activePiece.canvas_width * scale;
                let height = this.activePiece.canvas_height * scale;

                // 数量
                let countX = Math.max(Math.round(width / size) - 1, 0);
                let countY = Math.max(Math.round(height / size) - 1, 0);
                let offsetX = width / (countX + 1);
                let offsetY = height / (countY + 1);

                while (countX > 0) {
                    let x = 100 * (offsetX * countX) / width;
                    list.push({ left: x + '%', top: '0', height: '100%', width: '0' });
                    countX -= 1;
                }

                while (countY > 0) {
                    let y = 100 * (offsetY * countY) / height;
                    list.push({ left: '0', top: y + '%', height: '0', width: '100%' });
                    countY -= 1;
                }

                return list;
            }
        },

    },
    watch: {
        zoom () {
            this.updateSurface();
        },
        activeSurface () {
            this.updateSurface();
        },
        activePiece: {
            immediate: false,
            deep: true,
            handler (newval, oldval) {
                this.updatePiece(newval);
            },
        },
    },
    methods: {

        // 修改背景图
        updateMask () {
            const canvas = this.$refs.mask;
            const surface = this.activeSurface;
            const option = {
                type: "simple",
                form: "editor",
            };


            if (!canvas || !surface) {
                // 没有容器
            } else if (canvas.cache == surface.mask_image && canvas.scale == this.scale) {
                // 缓存相同
            } else {

                // 写画布
                surface.mask_image && DesignResource.loadImage(surface.mask_image, option).then(image => {
                    const rect = canvas.parentNode.getBoundingClientRect();
                    const ctx = canvas.getContext("2d")
                    // 清空画布
                    canvas.cache = surface.mask_image;
                    canvas.scale = this.scale;
                    canvas.width = rect.width * 2;
                    canvas.height = rect.height * 2;
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
                });

            }

        },

        // 更新打印区
        updatePiece (piece) {

            let render = this.renders[piece.canvas_name];
            let pieceCache = JSON.stringify(piece);

            if (!render) {
                // 没有渲染器
            } else if (pieceCache == render.pieceCache) {
                // 缓存相同
            } else if (render.status == 'reanding') {
                // 运行中
                render.change = true;
            } else {
                let option = {
                    canvas_name: piece.canvas_name,
                    canvas_scale: this.scale,
                    canvas_model: "simple",
                    canvas_width: piece.canvas_width,
                    canvas_height: piece.canvas_height,
                    design_layers: [],
                };
                // 改变了大小
                option.design_layers = piece.layers;
                render.pieceCache = pieceCache;
                render.change = false;
                render.status = 'reanding';

                render.editor.reset(option);
                render.editor.renderLayers().then((e) => {
                    render.status = 'complete';
                    render.change && this.updatePiece(piece)
                });
            }
        },

        // 更新面
        updateSurface () {
            // 设计面

            if (!this.$refs.mapping || !this.activeSurface) {
                // 没有内容
            } else {
                const rect = this.$refs.mapping.getBoundingClientRect();
                const piecesObject = Object.fromEntries(this.pieces.map((i) => [i.canvas_name, i]));
                const surface = this.activeSurface || {};
                const mapping = surface.mapping || [];
                const renders = this.renders;
                const piecesActive = []; // 显示的

                this.scale = 2 * Math.max(rect.width / surface.outer_width, rect.height / surface.outer_height);

                // 更新设计面
                mapping.map((mapper, index) => {

                    const piece = piecesObject[mapper.canvas_name];
                    let render = renders[mapper.canvas_name];

                    if (render) {
                        render.elem.style.display = 'block';
                        // 删掉缓存
                        render.pieceCache = ''
                    } else {
                        let option = {
                            canvas_name: piece.canvas_name,
                            canvas_scale: this.scale,
                            canvas_model: "simple",
                            canvas_width: piece.canvas_width,
                            canvas_height: piece.canvas_height,
                            design_layers: [],
                        };
                        const editor = new DesignEditor(Fabric, null, option);
                        render = {
                            elem: editor.fabric.lowerCanvasEl,
                            editor: editor,
                            canvas_name: piece.canvas_name,
                            piece: piece,
                            pieceCache: '',
                            status: '',
                            change: false,
                        };

                        this.$refs.mapping.appendChild(render.elem);
                        this.renders[mapper.canvas_name] = render;
                    }

                    // 修改位置
                    render.elem.style.maxWidth = 100 * (mapper.width / surface.outer_width) + "%";
                    render.elem.style.maxHeight = 100 * (mapper.height / surface.outer_height) + "%";
                    render.elem.style.left = 100 * (mapper.x / surface.outer_width) + "%";
                    render.elem.style.top = 100 * (mapper.y / surface.outer_height) + "%";
                    render.elem.style.transform = `rotate(${mapper.rotate}deg)`;
                    render.elem.style.zIndex = index + 1;

                    this.updatePiece(piece);
                    piecesActive.push(mapper.canvas_name);

                })

                // 隐藏其他图层
                Object.values(renders).map(render => piecesActive.indexOf(render.canvas_name) < 0 && (render.elem.style.display = 'none'));

                // 更新背景
                this.updateMask()
            }
        },
    },
    mounted () {
        this.updateSurface();
    },
    beforeDestroy () {
        this.render = {};
        this.$refs.layer && (this.$refs.layer.innerHTML = "");
    },
};
</script>

<style lang="scss" scoped>
.editor-render {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;
    box-sizing: border-box;
}
.editor-render-mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    canvas {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
}

.editor-gridline-line {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
    z-index: 1;

    span {
        position: absolute;
        box-sizing: border-box;
        border-left: 1px solid rgb(35, 154, 194, 0.55);
        border-top: 1px solid rgb(35, 154, 194, 0.55);
    }
    svg {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        opacity: 0.8;
    }
}

.editor-render-mapping {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    &::v-deep {
        canvas {
            position: absolute;
            top: 0;
            left: 0;
        }
    }
}

.editor-gridline-border {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    border: 1px dashed #239ac2;
    box-sizing: border-box;
    z-index: 2;
    pointer-events: none;
}
</style>
